import type { Feature, Polygon } from 'geojson'
import type { FillStyle } from './types'
import BaseLayer from './base-layer'

export interface BaseFillLayerOption<T> {
  id: string
  name: string
  getFeature: (t: T) => Feature<Polygon>
  style: FillStyle
  visible?: boolean
  before?: string | null
}

export default class BaseFillLayer<T> extends BaseLayer {
  private style: FillStyle
  private getFeature: (t: T) => Feature<Polygon>

  constructor(opts: BaseFillLayerOption<T>, dat: T[] | undefined = undefined) {
    super(
      opts.id,
      opts.name,
      opts.visible !== false,
      dat?.map((e) => opts.getFeature(e)),
      opts.before === undefined ? 'overlay#fill' : opts.before
    )
    this.style = this.makeStyle(opts.style)
    this.getFeature = opts.getFeature
  }

  public clearData() {
    this.repaint([])
  }

  public updateData(lst: T[] | undefined) {
    if (!lst || lst.length === 0) {
      this.repaint([])
      return
    }
    const fLst = lst.map((e) => this.getFeature(e))
    this.repaint(fLst)
  }

  public setStyle(style: FillStyle) {
    style = this.makeStyle(style)
    const origin = this.style
    this.style = style
    const { map, id } = this
    if (!map) {
      return
    }
    if (style.fillColor !== origin.fillColor) {
      map.setPaintProperty(id, 'fill-color', style.fillColor)
    }
    if (style.fillOutlineColor !== origin.fillOutlineColor) {
      map.setPaintProperty(id, 'fill-outline-color', style.fillOutlineColor)
    }
    if (style.fillOpacity !== origin.fillOpacity) {
      map.setPaintProperty(id, 'fill-opacity', style.fillOpacity)
    }
  }

  protected makeMapBoxGLLayer(): Omit<mapboxgl.Layer, 'source'> {
    const { id, style } = this
    return {
      id: id,
      type: 'fill',
      layout: {},
      paint: {
        'fill-color': style.fillColor,
        'fill-outline-color': style.fillOutlineColor,
        'fill-opacity': style.fillOpacity
      }
    }
  }

  private makeStyle(s: FillStyle): FillStyle {
    return Object.assign({}, s)
  }
}
